package core;

import math.Matrix4;
import math.Quaternion;
import math.Vector3;

public class Camera {
    public float[] position;
    public float[] target;
    public float[] up;
    public float[] direction;
    public float[] right;
    public float[] scale;
    public Matrix4 VPmatrix;

    public float fov;
    public float aspect;
    public float near;
    public float far;
    public Quaternion quaternion;
    public Matrix4 matrix;
    public Matrix4 matrixWorld;
    public Matrix4 projectionMatrix;

    public Camera(float fov,float aspect,float near,float far){
        this.fov = fov;
        this.aspect = aspect;
        this.near = near;
        this.far = far;

        this.position = new float[]{0, 0, 10};
        this.target = new float[]{0, 0, 0};
        this.up = new float[]{0, 1, 0};

        this.VPmatrix = new Matrix4();

        this.direction = new float[]{0, 0, -1};
        this.right = new float[]{1, 0, 0};

        this.scale = new float[]{1, 1, 1};
        this.quaternion = new Quaternion();
        this.matrix = new Matrix4();
        this.matrixWorld = this.matrix;
        this.projectionMatrix = new Matrix4();

        this.updateAll();
    }

    public void setPosition(float[] position){
        this.position = position;
        this.updateAll();
    }

    public void updateAll(){
        this.updateOption();
        this.updateMatrix();
        this.updateVPMatrix();
    }

    void updateOption(){
        Vector3 targetV3 = new Vector3().fromArray(this.target);
        Vector3 positionV3 = new Vector3().fromArray(this.position);
        Vector3 upV3 = new Vector3().fromArray(this.up);

        Vector3 directionV3 = new Vector3().subVectors(targetV3, positionV3).normalize();
        this.direction = directionV3.toArray();

        Vector3 rightV3 = new Vector3().crossVectors(directionV3, upV3).normalize();
        this.right = rightV3.toArray();

        // this.up = new Vector3().crossVectors(rightV3, directionV3).normalize().toArray();
    }

    void updateMatrix(){
        Quaternion quaternionD = new Quaternion().setFromUnitVectors(new Vector3(0,0,-1), new Vector3().fromArray(this.direction));
        Vector3 right2 = new Vector3(1,0,0).applyQuaternion(quaternionD);
        Quaternion quaternionR = new Quaternion().setFromUnitVectors(right2, new Vector3().fromArray(this.right));
        Quaternion quaternion = new Quaternion().multiplyQuaternions(quaternionR, quaternionD);
        this.quaternion = quaternion;

        this.matrix.compose( new Vector3().fromArray(this.position), this.quaternion, new Vector3().fromArray(this.scale) );
        this.projectionMatrix = new Matrix4().setPerspective(this.fov, this.aspect, this.near, this.far);
        // this.updateMatrixWorld ();
    }

    void updateVPMatrix(){
        this.VPmatrix = new Matrix4().setPerspective(this.fov, this.aspect, this.near, this.far);
        Matrix4 Vmatrix = new Matrix4().getInverse(this.matrix);
        this.VPmatrix.concat(Vmatrix);
        //等价
        // this.VPmatrix.lookAt2(this.position[0],this.position[1],this.position[2], this.target[0],this.target[1],this.target[2], this.up[0],this.up[1],this.up[2]);
    }
}
